/////////////////////////////////////////////////////////////////////////
//
// Amuse Engine SDK - core/math
// Copyright(c) 2015.  All Rights Reserved
//
// File:		AEVector4f.h
// Author:		Gianluca Belardelli
// Date:		29/07/2013
//
// Revision:
//				001 - 29/07/2013
//					+ Revisione iniziale
//				002 - 21/04/2015
//					+ Aggiunti i metodi GetX, GetY, GetZ e GetW
//					+ Sistemata la documentazione
/////////////////////////////////////////////////////////////////////////
#ifndef _AEVECTOR4F_H_
#define _AEVECTOR4F_H_

#ifndef _AEMATH_H_
#	error Includere il file core/math/AEMath.h invece di questo.
#endif

// Compile time error checking
AECOMPILEERRMSG( AE_VECTOR4F_TEMPLATE_CONFIGURATION_NOT_IMPLEMENTED );
AECOMPILEERRMSG( AE_VECTOR4F_SUBVECTOR_INDEX_OUT_OF_RANGE );
AECOMPILEERRMSG( AE_VECTOR4F_NOT_IMPLEMENTED_FOR_THIS_VECTOR_LENGTH );
AECOMPILEERRMSG( AE_VECTOR4F_UNSUPPORTED_VECTOR_LENGTH );

#define AE_VECTOR4F_SUBINDEX_CHECK           AE_COMPILE_TIME_ASSERT( ( I >= 0 ) && ( I < 4 ), AE_VECTOR4F_SUBVECTOR_INDEX_OUT_OF_RANGE)
#define AE_VECTOR4F_NOT_IMPLEMENTED          AE_COMPILE_TIME_ASSERT( N == 0, AE_VECTOR4F_NOT_IMPLEMENTED_FOR_THIS_VECTOR_LENGTH)
#define AE_VECTOR4F_UNSUPPORTED_LENGTH_CHECK AE_COMPILE_TIME_ASSERT( ( N > 0 ) && ( N <= 4 ), AE_VECTOR4F_UNSUPPORTED_VECTOR_LENGTH)
#define AE_VECTOR4F_TEMPLATE_CONFIG_NOT_IMPLEMENTED AE_COMPILE_TIME_ASSERT( A < 0, AE_VECTOR4F_TEMPLATE_CONFIGURATION_NOT_IMPLEMENTED)

/// \brief
/// La classe rappresenta un vettore a quattro componenti e contiene quattro numeri in virgola mobile a seconda della
/// definizione di AEFLOAT32. Ci sono implementazioni SIMD ottimizzate disponibili per diverse piattaforme.
/// Esse utilizzano strutture dati specifiche della piattaforma. Per rendere la classe portabile, nulla deve essere assunto
/// per quanto concerne la disposizione interna dei quattro numeri in virgola mobile .
/// Sono stati implementati metodi template per l'accesso ottimizzato alle componenti del vettore.
/// E' consigliabile utilizzare tali metodi quando si conosce a priori l'elemento da utilizzare. Negli
/// altri casi si pu&ograve; utilizzare il rispettivo metodo non template.
/// Per accedere ai contenuti di un vettore, &egrave; raccomandato l'utilizzo dei metodi Get/SetComponent i quali,
/// operando con valori di tipo AESimdFloat32, che a loro volta hanno metodi efficienti per l'esecuzione 
/// di operazioni aritmetiche e non, evitano di uscire fuori dalla pipeline di elaborazione SIMD.
/// La precisione a 23bit &egrave; quasi come la versione float IEEE, ma aumenta sostanzialmente la velocit&agrave;
/// di esecuzione a discapito della precisione di calcolo. La precisione a 12bit offre un esecuzione ancora
/// pi&ugrave; veloce ma una precisione nettamente inferiore. E' consigliabile utilizzare la classe partendo da una
/// precisione Full per poi eventualmente abbassarla a seconda del risultato richiesto. 
class AE_COREDLLIMPEXP AEVector4f
{
// Members
public:
	/// \brief
	/// Membro pubblico contenente i quattro valori float
	/// che rappresentano le componenti X, Y, Z e W del
	/// vettore.
	AE_ALIGN16 AEQuadFloat32 m_qfVector;

// Methods
public:
	AE_DECLARE_NONVIRTUAL_CLASS_ALLOCATOR( TOBEDFINED, AEVector4f );
	
	/** @name Costruttori */
	/// @{
	/// \brief Costruttore. Non inizializza il vettore.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD></TD><TD>*</TD><TD>*</TD><TD></TD></TR></TABLE>
	AE_FORCEINLINE AEVector4f( void );

	/// \brief Costruttore. Inizializza tutte le componenti del vettore con
	/// il valore impostato nel parametro \a qfValue.
	/// \param qfValue Valore assegnato alle componenti.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD></TD><TD>*</TD><TD>*</TD><TD></TD></TR></TABLE>

	AE_FORCEINLINE explicit AEVector4f( const AEQuadFloat32 &qfValue );

	/// \brief Costruttore. Inizializza individualmente ogni componente.
	/// \param fX Valore della componente X.
	/// \param fY Valore della componente Y.
	/// \param fZ Valore della componente Z.
	/// \param fW Valore della componente W. Per default &egrave; 0.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD></TD><TD>*</TD><TD>*</TD><TD></TD></TR></TABLE>
	AE_FORCEINLINE AEVector4f( AEFLOAT32 fX, AEFLOAT32 fY, AEFLOAT32 fZ, AEFLOAT32 fW=AEFLOAT32(0) );

	/// \brief Costruttore di copia.
	/// \param vcCopy Referenza all'oggetto da copiare.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD></TD><TD>*</TD><TD>*</TD><TD></TD></TR></TABLE>
	AE_FORCEINLINE AEVector4f( const AEVector4f &vcCopy );
	
	/// @}
	/** @name Funzioni statiche */
	/// @{
	/// \brief Ritorna un vettore con tutte le componenti impostate a 0.0.
	AE_FORCEINLINE static const AEVector4f ZeroVector( void );

	/// \brief Ritorna un vettore definito nelle costanti AEVectorConstant.
	template<AEINT32 vectorConstant>
	AE_FORCEINLINE static const AEVector4f& AE_CALL GetConstant ( void );

	/// \brief Ritorna un vettore definito nelle costanti AEVectorConstant.
	/// \remark Utilizzare questo metodo solo se la costante non &egrave; conosciuta
	/// durante la compilazione.
	AE_FORCEINLINE static const AEVector4f& AE_CALL GetConstant( AEVectorConstant vcConstant );

	/// @}
	/** @name Conversioni */
	/// @{
	/// \brief Ritorna un vettore di tipo AEVector2f con le componenti
	/// X e Y uguali alle componenti X e Y di questo vettore.
	AE_FORCEINLINE const AEVector2 GetAsVec2( void ) const;

	/// @}
	/** @name Inizializzazione base */
	/// @{
	/// \brief Imposta tutte le componenti del vettore a 0.0.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD></TD><TD>*</TD><TD>*</TD><TD></TD></TR></TABLE>
	AE_FORCEINLINE void SetZero( void );

	/// \brief Imposta le componenti del vettore con i valori dati.
	/// \param fX Valore della componente X.
	/// \param fY Valore della componente Y.
	/// \param fZ Valore della componente Z.
	/// \param fW Valore della componente W.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD></TD><TD>*</TD><TD>*</TD><TD></TD></TR></TABLE>
	AE_FORCEINLINE void Set( AESimdFloat32ConstRef fX, AESimdFloat32ConstRef fY, AESimdFloat32ConstRef fZ, AESimdFloat32ConstRef fW );

	/// \brief Imposta le componenti del vettore con i valori dati.
	/// \param fX Valore della componente X.
	/// \param fY Valore della componente Y.
	/// \param fZ Valore della componente Z.
	/// \param fW Valore della componente W.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD></TD><TD>*</TD><TD>*</TD><TD></TD></TR></TABLE>
	AE_FORCEINLINE void Set( AEFLOAT32 fX, AEFLOAT32 fY, AEFLOAT32 fZ, AEFLOAT32 fW );

	/// \brief Imposta tutte le componenti del vettore con il valore dato.
	/// \param fValue Valore da impostare.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD></TD><TD>*</TD><TD>*</TD><TD></TD></TR></TABLE>
	AE_FORCEINLINE void SetAll( const AEFLOAT32 &fValue );

	/// \brief Imposta tutte le componenti del vettore con il valore dato.
	/// \param fValue Valore da impostare.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD></TD><TD>*</TD><TD>*</TD><TD></TD></TR></TABLE>
	AE_FORCEINLINE void SetAll( AESimdFloat32ConstRef fValue );

	/// \brief Imposta la componente specificata dal parametro template I a zero.
	/// \tparam <I> Componente da azzerare. 0, 1, 2, 3 corrispondono rispettivamente a X, Y, Z, W.
	/// \remark E' preferibile utilizzare questo metodo quando l'indice della
	/// componente &egrave; conosciuto durante la compilazione.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD></TD><TD>*</TD><TD>*</TD><TD></TD></TR></TABLE>
	template <AEINT32 I> AE_FORCEINLINE void ZeroComponent( void );

	/// \brief Imposta la componente specificata da \a nIndex a 0.0.
	/// \param nIndex Componente da azzerare. 0, 1, 2, 3 corrispondono rispettivamente a X, Y, Z, W.
	/// \remark Utilizzare questo metodo solo se l'indice della componente
	/// non &egrave; conosciuto durante la compilazione.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD></TD><TD>*</TD><TD>*</TD><TD></TD></TR></TABLE>
	AE_FORCEINLINE void ZeroComponent( const AEINT32 nIndex );

	/// @}
	/** @name Metodi di calcolo */
	/// @{
	/// \brief Addiziona a questo vettore il vettore passato nel parametro
	/// \code ( this += vcVector ) \endcode
	/// \param vcVector Vettore da addizionare.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD>*</TD><TD></TD><TD></TD><TD></TD></TR></TABLE>
	AE_FORCEINLINE void Add( AEVector4fRefParam vcVector );

	/// \brief Sottrae a questo vettore il vettore passato nel parametro
	/// \code ( this -= vcVector ) \endcode
	/// \param vcVector Vettore da sottrarre.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD>*</TD><TD></TD><TD></TD><TD></TD></TR></TABLE>
	AE_FORCEINLINE void Sub( AEVector4fRefParam vcVector );

	/// \brief Moltiplica questo vettore con il vettore passato nel parametro.
	/// \code ( this *= vcVector ) \endcode
	/// \param vcVector Vettore da moltiplicare.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD>*</TD><TD></TD><TD></TD><TD></TD></TR></TABLE>
	AE_FORCEINLINE void Mul( AEVector4fRefParam vcVector );

	/// \brief Moltiplica ogni componente di questo vettore con il
	/// valore fValue. \code ( this *= fValue ) \endcode
	/// \param fValue Valore da moltiplicare.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD>*</TD><TD></TD><TD></TD><TD></TD></TR></TABLE>
	AE_FORCEINLINE void Mul( AESimdFloat32ConstRef fValue );

	/// \brief Divide questo vettore con il vettore passato nel parametro.
	/// \code( this /= vcVector ) \endcode
	/// \param vcVector Vettore da moltiplicare.
	/// \remark Precisione di default a 23bit, la divisione
	/// per 0 non viene controllata.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD></TD><TD>*</TD><TD>*</TD><TD></TD></TR></TABLE>
	AE_FORCEINLINE void Div( AEVector4fRefParam vcVector );

	/// @}
	/** @name Inizializzazione avanzata */
	/// @{
	/// \brief Imposta questo vettore con la somma dei due vettori
	/// passati nel parametro \code ( this = vcVector1 + vcVector2 ) \endcode
	/// \param vcVector1 Primo vettore da addizionare.
	/// \param vcVector2 Secondo vettore da addizionare.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD></TD><TD>*</TD><TD>*</TD><TD></TD></TR></TABLE>
	AE_FORCEINLINE void SetAdd( AEVector4fRefParam vcVector1, AEVector4fRefParam vcVector2 );

	/// \brief Imposta questo vettore con la differenza tra i due vettori
	/// passati nel parametro \code ( this = vcVector1 - vcVector2 ) \endcode 
	/// \param vcVector1 Primo vettore.
	/// \param vcVector2 Secondo vettore.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD></TD><TD>*</TD><TD>*</TD><TD></TD></TR></TABLE>
	AE_FORCEINLINE void SetSub( AEVector4fRefParam vcVector1, AEVector4fRefParam vcVector2 );

	/// \brief Imposta questo vettore con il prodotto tra i due vettori
	/// passati nel parametro \code ( this = vcVector1 * vcVector2 ) \endcode 
	/// \param vcVector1 Primo vettore.
	/// \param vcVector2 Secondo vettore.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD></TD><TD>*</TD><TD>*</TD><TD></TD></TR></TABLE>
	AE_FORCEINLINE void SetMul( AEVector4fRefParam vcVector1, AEVector4fRefParam vcVector2 );

	/// \brief Imposta questo vettore con il prodotto tra il valore \a fValue
	/// e il vettore passati nel parametro \code ( this = fValue * vcVector ) \endcode 
	/// \param fValue Valore float.
	/// \param vcVector Vettore.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD>*</TD><TD></TD><TD></TD><TD></TD></TR></TABLE>
	AE_FORCEINLINE void SetMul( AESimdFloat32ConstRef fValue, AEVector4fRefParam vcVector );

	/// \brief Imposta questo vettore con il prodotto tra il valore \a fValue
	/// e il vettore passati nel parametro \code ( this = fValue * vcVector ) \endcode
	/// \param vcVector Vettore.
	/// \param fValue Valore float.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD></TD><TD>*</TD><TD>*</TD><TD></TD></TR></TABLE>
	AE_FORCEINLINE void SetMul( AEVector4fRefParam vcVector, AESimdFloat32ConstRef fValue );
	
	/// \brief Imposta questo vettore con la differenza tra il vettore \a vcVector1
	/// e il prodotto di \a vcVector2 moltiplicato per \a fValue.
	/// \code ( this = vcVector1 - vcVector2*fValue ) \endcode
	/// \param vcVector1 Primo vettore.
	/// \param vcVector2 Secondo vettore.
	/// \param fValue Valore float.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD></TD><TD>*</TD><TD>*</TD><TD></TD></TR></TABLE>
	AE_FORCEINLINE void SetSubMul( AEVector4fRefParam vcVector1, AEVector4fRefParam vcVector2, AESimdFloat32ConstRef fValue );
	
	/// \brief Imposta questo vettore con la differenza tra il vettore \a vcVector1
	/// e il prodotto di \a vcVector2 moltiplicato per \a vcVector3.
	/// \code ( this = vcVector1 - vcVector2*vcVector3 ) \endcode
	/// \param vcVector1 Primo vettore.
	/// \param vcVector2 Secondo vettore.
	/// \param vcVector3 Terzo vettore.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD></TD><TD>*</TD><TD>*</TD><TD></TD></TR></TABLE>
	AE_FORCEINLINE void SetSubMul( AEVector4fRefParam vcVector1, AEVector4fRefParam vcVector2, AEVector4fRefParam vcVector3 );

	/// \brief Imposta questo vettore con la somma tra il vettore \a vcVector1
	/// e il prodotto di \a vcVector2 moltiplicato per \a fValue.
	/// \code ( this = vcVector1 + vcVector2*fValue ) \endcode
	/// \param vcVector1 Primo vettore.
	/// \param vcVector1 Secondo vettore.
	/// \param fValue Valore float.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD></TD><TD>*</TD><TD>*</TD><TD></TD></TR></TABLE>
	AE_FORCEINLINE void SetAddMul( AEVector4fRefParam vcVector1, AEVector4fRefParam vcVector2, AESimdFloat32ConstRef fValue );

	/// \brief Imposta questo vettore con la somma tra il vettore \a vcVector1
	/// e il prodotto di \a vcVector2 moltiplicato per \a vcVector3.
	/// \code ( this = vcVector1 + vcVector2*vcVector3 ) \endcode
	/// \param vcVector1 Primo vettore al quale sommare il prodotto degli altri due.
	/// \param vcVector2 Vettore da moltiplicare
	/// \param vcVector3 Terzo vettore che rappresenta il moltiplicando.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD></TD><TD>*</TD><TD>*</TD><TD></TD></TR></TABLE>
	AE_FORCEINLINE void SetAddMul( AEVector4fRefParam vcVector1, AEVector4fRefParam vcVector2, AEVector4fRefParam vcVector3 );

	/// \brief Addiziona a questo vettore il prodotto tra \a vcVector e \a fValue
	/// \code ( this += vcVector*fValue ) \endcode
	/// \param vcVector Vettore da moltiplicare.
	/// \param fValue Valore float che rappresenta il moltiplicando.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD>*</TD><TD></TD><TD></TD><TD></TD></TR></TABLE>
	AE_FORCEINLINE void AddMul( AEVector4fRefParam vcVector, AESimdFloat32ConstRef fValue );

	/// \brief Addiziona a questo vettore il prodotto tra \a vcVector e \a fValue
	/// \code ( this += fValue*vcVector ) \endcode
	/// \param fValue Valore float da moltiplicare.
	/// \param vcVector Vettore che rappresenta il moltiplicando.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD>*</TD><TD></TD><TD></TD><TD></TD></TR></TABLE>
	AE_FORCEINLINE void AddMul( AESimdFloat32ConstRef fValue, AEVector4fRefParam vcVector );

	/// \brief Addiziona a questo vettore il prodotto tra \a vcVector1 e \a vcVector2.
	/// \code ( this += vcVector1*vcVector2 ) \endcode
	/// \param vcVector1 Vettore da moltiplicare.
	/// \param vcVector2 Vettore che rappresenta il moltiplicando.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD>*</TD><TD></TD><TD></TD><TD></TD></TR></TABLE>
	AE_FORCEINLINE void AddMul( AEVector4fRefParam vcVector1, AEVector4fRefParam vcVector2 );

	/// \brief Sottrae a questo vettore il prodotto tra \a vcVector e \a fValue
	/// \code ( this -= vcVector*fValue ) \endcode
	/// \param vcVector Vettore.
	/// \param fValue Valore float.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD>*</TD><TD></TD><TD></TD><TD></TD></TR></TABLE>
	AE_FORCEINLINE void SubMul( AEVector4fRefParam vcVector, AESimdFloat32ConstRef fValue );

	/// \brief Sottrae a questo vettore il prodotto tra \a vcVector1 e \a vcVector2.
	/// \code ( this -= vcVector1*vcVector2 ) \endcode
	/// \param vcVector1 Primo vettore.
	/// \param vcVector2 Secondo vettore.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD>*</TD><TD></TD><TD></TD><TD></TD></TR></TABLE>
	AE_FORCEINLINE void SubMul( AEVector4fRefParam vcVector1, AEVector4fRefParam vcVector2 );

	/// \brief Sottrae a questo vettore il prodotto tra \a vcVector e \a fValue
	/// \code ( this -= fValue*vcVector ) \endcode
	/// \param fValue Valore di tipo AESimdFloat32ConstRef con il quale moltiplicare il vettore.
	/// \param vcVector Vettore da moltiplicare con il valore fValue.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD>*</TD><TD></TD><TD></TD><TD></TD></TR></TABLE>
	AE_FORCEINLINE void SubMul( AESimdFloat32ConstRef fValue, AEVector4fRefParam vcVector );

	/// \brief Imposta questo vettore con il risultato del prodotto cross tra \a vcVector1 e \a vcVector2
	/// \code ( this = vcVector1 cross vcVector2 ) \endcode
	/// \param vcVector1 Primo vettore.
	/// \param vcVector2 Secondo vettore.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD></TD><TD>*</TD><TD>*</TD><TD></TD></TR></TABLE>
	AE_FORCEINLINE void SetCross( AEVector4fRefParam vcVector1, AEVector4fRefParam vcVector2 );

	/// \brief Imposta tutte le componenti di questo vettore con il risultato
	/// della somma delle N componenti di \a vcVector \code ( this = AEVector4f(x+y+z+w) ) \endcode
	/// \param vcVector Vettore dal quale sommare le componenti.
	/// \tparam <N> Numero delle componenti da sommare. Inserendo un valore < 2 o > 4 
	/// sar&agrave; generato l'errore AECompileError::AE_VECTOR4F_NOT_IMPLEMENTED_FOR_THIS_VECTOR_LENGTH
	/// durante la compilazione.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD>*</TD><TD></TD><TD></TD><TD></TD></TR></TABLE>
	template <AEINT32 N> AE_FORCEINLINE void SetHorizontalAdd( AEVector4fRefParam vcVector );
	
	/// \brief Esegue la somma delle N componenti selezionate. 
	/// \code ( return x+y+z+w ) \endcode
	/// \tparam <N> Numero delle componenti da sommare. Inserendo un valore < 2 o > 4 
	/// sar&agrave; generato l'errore AECompileError::AE_VECTOR4F_NOT_IMPLEMENTED_FOR_THIS_VECTOR_LENGTH
	/// durante la compilazione.
	/// \return Valore di tipo AESimdFloat32 contenente la somma.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD></TD><TD>*</TD><TD>*</TD><TD></TD></TR></TABLE>
	template <AEINT32 N> AE_FORCEINLINE const AESimdFloat32 GetHorizontalAdd( void ) const;

	/// \brief Esegue il prodotto delle N componenti selezionate. 
	/// \code ( return x*y*z*w ) \endcode
	/// \tparam <N> Numero delle componenti da moltiplicare. Inserendo un valore < 2 o > 4 
	/// sar&agrave; generato l'errore AECompileError::AE_VECTOR4F_NOT_IMPLEMENTED_FOR_THIS_VECTOR_LENGTH
	/// durante la compilazione.
	/// \return Valore float del prodotto.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD></TD><TD>*</TD><TD>*</TD><TD></TD></TR></TABLE>
	template <AEINT32 N> AE_FORCEINLINE const AESimdFloat32 GetHorizontalMul( void ) const;

	/// \brief Imposta tutte le componenti di questo vettore con il valore
	/// massimo delle N componenti di \a vcVector \code ( this = AEVector4f( max(x,y,z,w) ) ) \endcode
	/// \param vcVector Vettore dal quale ricavare il valore massimo.
	/// \tparam <N> Numero delle componenti da utilizzare.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD>*</TD><TD></TD><TD></TD><TD></TD></TR></TABLE>
	template <AEINT32 N> AE_FORCEINLINE void SetHorizontalMax( AEVector4fRefParam vcVector );
	
	/// \brief Ritorna il valore massimo presente nelle componenti del vettore
	/// \code ( return max(x,y,z,w) \endcode 
	/// \tparam <N> Numero delle componenti da utilizzare.
	/// \return Valore float della componente maggiore.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD></TD><TD>*</TD><TD>*</TD><TD></TD></TR></TABLE>
	template <AEINT32 N> AE_FORCEINLINE const AESimdFloat32 GetHorizontalMax( void ) const;
	
	/// \brief Imposta tutte le componenti di questo vettore con il valore
	/// minimo delle N componenti di \a vcVector \code ( this = AEVector4f( min(x,y,z,w) ) ) \endcode
	/// \param vcVector Vettore dal quale ricavare il valore minimo.
	/// \tparam <N> Numero delle componenti da utilizzare.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD>*</TD><TD></TD><TD></TD><TD></TD></TR></TABLE>
	template <AEINT32 N> AE_FORCEINLINE void SetHorizontalMin( AEVector4fRefParam vcVector );

	/// \brief Ritorna il valore minimo presente nelle componenti del vettore
	/// \code ( return min(x,y,z,w) \endcode 
	/// \tparam <N> Indice della componente.
	/// \return Valore float della componente pi&ugrave; piccola.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD></TD><TD>*</TD><TD>*</TD><TD></TD></TR></TABLE>
	template <AEINT32 N> AE_FORCEINLINE const AESimdFloat32 GetHorizontalMin( void ) const;

	/// \brief Imposta questo vettore con il reciproco del vettore passato nel parametro.
	/// \code ( this = 1/vcVector ) \endcode 
	/// \param vcVector Vettore sul quale calcolare il reciproco.
	/// \remark Precisione di default AEMathAccuracyMode::AE_ACC_23_BIT, la divisione
	/// per 0 non viene controllata AEMathDivByZeroMode::AE_DIV_IGNORE.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD></TD><TD>*</TD><TD>*</TD><TD></TD></TR></TABLE>
	AE_FORCEINLINE void SetReciprocal( AEVector4fRefParam vcVector );

	/// \brief Imposta questo vettore con il reciproco del vettore passato nel parametro.
	/// \code ( this = 1/vcVector ) \endcode 
	/// \param vcVector Vettore sul quale calcolare il reciproco.
	/// \tparam <A> Imposta la precisione tramite \ref AEMathAccuracyMode.
	/// \tparam <D> Controlla la divisione per 0 tramite \ref AEMathDivByZeroMode.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD></TD><TD>*</TD><TD>*</TD><TD></TD></TR></TABLE>
	template <AEMathAccuracyMode A, AEMathDivByZeroMode D> AE_FORCEINLINE void SetReciprocal( AEVector4fRefParam vcVector );

	/// \brief Imposta questo vettore con la radice quadrata del vettore passato nel parametro.
	/// \code ( this = sqrt(vcVector) ) \endcode
	/// \param vcVector Vettore sul quale calcolare la radice quadrata.
	/// \remark Precisione di default AEMathAccuracyMode::AE_ACC_23_BIT, valore negativo per la
	/// radice quadrata AEMathNegSqrtMode::AE_SQRT_SET_ZERO.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD></TD><TD>*</TD><TD>*</TD><TD></TD></TR></TABLE>
	AE_FORCEINLINE void SetSqrt( AEVector4fRefParam vcVector );

	/// \brief Imposta questo vettore con la radice quadrata del vettore passato nel parametro.
	/// \code ( this = sqrt(vcVector) ) \endcode
	/// \param vcVector Vettore sul quale calcolare la radice quadrata.
	/// \tparam <A> Imposta la precisione tramite \ref AEMathAccuracyMode.
	/// \tparam <S> Controlla i valori negativi tramite \ref AEMathNegSqrtMode.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD></TD><TD>*</TD><TD>*</TD><TD></TD></TR></TABLE>
	template <AEMathAccuracyMode A, AEMathNegSqrtMode S> AE_FORCEINLINE void SetSqrt( AEVector4fRefParam vcVector );

	/// \brief Imposta questo vettore con la radice quadrata inversa del vettore 
	/// passato nel parametro. \code ( this = 1/sqrt(vcVector) ) \endcode
	/// \param vcVector Vettore sul quale calcolare la radice quadrata.
	/// \remark Precisione di default impostata con AEMathAccuracyMode::AE_ACC_23_BIT. 
	/// La sqrt negativa viene controllata con AEMathNegSqrtMode::AE_SQRT_SET_ZERO.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD></TD><TD>*</TD><TD>*</TD><TD></TD></TR></TABLE>
	AE_FORCEINLINE void SetSqrtInverse( AEVector4fRefParam vcVector );

	/// \brief Imposta questo vettore con la radice quadrata inversa del vettore 
	/// passato nel parametro. \code ( this = 1/sqrt(vcVector) ) \endcode
	/// \param vcVector Vettore sul quale calcolare la radice quadrata.
	/// \tparam <A> Imposta la precisione tramite \ref AEMathAccuracyMode.
	/// \tparam <S> Controlla i valori negativi tramite \ref AEMathNegSqrtMode.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD></TD><TD>*</TD><TD>*</TD><TD></TD></TR></TABLE>
	template <AEMathAccuracyMode A, AEMathNegSqrtMode S> AE_FORCEINLINE void SetSqrtInverse( AEVector4fRefParam vcVector );

	/// \brief Imposta le prime N componenti di questo vettore cambiandogli il segno.
	/// \code ( this = N ? -v : v ) \endcode
	/// \tparam <N> Numero delle componenti.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD></TD><TD></TD><TD>*</TD><TD></TD></TR></TABLE>
	template <AEINT32 N> AE_FORCEINLINE void SetNeg( AEVector4fRefParam vcVector );

	/// \brief Ritorna il prodotto dot tra questo vettore e il vettore passato come
	/// parametro prendendo solo le prime N componenti. 
	/// \code ( return this dot vcVector ) \endcode
	/// \param vcVector Vettore con il quale eseguire il dot product.
	/// \tparam <N> Numero delle componenti da includere nel calcolo. Inserendo un valore < 2 o > 4 
	/// sar&agrave; generato l'errore AECompileError::AE_VECTOR4F_NOT_IMPLEMENTED_FOR_THIS_VECTOR_LENGTH
	/// durante la compilazione.
	/// \return Un valore AESimdFloat32 contenente il dot product tra i due vettori.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD></TD><TD>*</TD><TD>*</TD><TD></TD></TR></TABLE>
	template <AEINT32 N> AE_FORCEINLINE const AESimdFloat32 GetDot( AEVector4fRefParam vcVector ) const;

	/// \brief Ritorna il prodotto dot tra questo vettore e il vettore passato come
	/// parametro impostando a 1.0 la componente W di \a vcVector.
	/// \param vcVector Vettore con il quale eseguire il dot product.
	/// \return Un valore AESimdFloat32 contenente il dot product tra i due vettori.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD></TD><TD>*</TD><TD>*</TD><TD></TD></TR></TABLE>
	AE_FORCEINLINE const AESimdFloat32 Dot4xyz1( AEVector4fRefParam vcVector ) const;
	
	/// \brief Imposta tutte le componenti di questo vettore con il valore risultante
	/// dal dot product delle N componenti di \a vcVector1 e \a vcVector2.
	/// \code ( this = vcVector1 dot vcVector2 ) \endcode
	/// \param vcVector1 Primo vettore con il quale eseguire il dot product.
	/// \param vcVector2 Secondo vettore con il quale eseguire il dot product.
	/// \tparam <N> Numero delle componenti da includere nel calcolo. Inserendo un valore < 2 o > 4 
	/// sar&agrave; generato l'errore AECompileError::AE_VECTOR4F_NOT_IMPLEMENTED_FOR_THIS_VECTOR_LENGTH
	/// durante la compilazione.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD>*</TD><TD></TD><TD></TD><TD></TD></TR></TABLE>
	template <AEINT32 N> AE_FORCEINLINE void SetDot( AEVector4fRefParam vcVector1, AEVector4fRefParam vcVector2 );

	/// \brief Imposta le componenti di questo vettore con il risultato
	/// della divisione tra \a vcVector1 e \a vcVector2.
	/// \code ( this = vcVector1 / vcVector2 ) \endcode
	/// \param vcVector1 Vettore divisore.
	/// \param vcVector2 Vettore dividendo.
	/// \tparam <A> Imposta la precisione tramite \ref AEMathAccuracyMode.
	/// \tparam <D> Controlla la divisione per 0 tramite \ref AEMathDivByZeroMode.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD></TD><TD>*</TD><TD>*</TD><TD></TD></TR></TABLE>
	template <AEMathAccuracyMode A, AEMathDivByZeroMode D> AE_FORCEINLINE void SetDiv( AEVector4fRefParam vcVector1, AEVector4fRefParam vcVector2 );

	/// \brief Imposta le componenti di questo vettore con il risultato
	/// della divisione tra \a vcVector1 e \a vcVector2.
	/// \code ( this = vcVector1 / vcVector2 ) \endcode
	/// \param vcVector1 Vettore divisore.
	/// \param vcVector2 Vettore dividendo.
	/// \remark Precisione di default AEMathAccuracyMode::AE_ACC_23_BIT, la divisione
	/// per 0 non viene controllata AEMathDivByZeroMode::AE_DIV_IGNORE.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD></TD><TD>*</TD><TD>*</TD><TD></TD></TR></TABLE>
	AE_FORCEINLINE void SetDiv( AEVector4fRefParam vcVector1, AEVector4fRefParam vcVector2 );

	/// \brief Esegue la divisione tra questo vettore e il vettore passato come parametro.
	/// \code ( this /= vcVector ) \endcode
	/// \param Vettore contenente il dividendo.
	/// \tparam <A> Imposta la precisione tramite \ref AEMathAccuracyMode.
	/// \tparam <D> Controlla la divisione per 0 tramite \ref AEMathDivByZeroMode.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD></TD><TD>*</TD><TD>*</TD><TD></TD></TR></TABLE>
	template <AEMathAccuracyMode A, AEMathDivByZeroMode D> AE_FORCEINLINE void Div( AEVector4fRefParam vcVector );
	
	/// \brief Ritorna la lunghezza di questo vettore rappresentato dalle N componenti.
	/// \code return sqrt(this dot this) \endcode
	/// \tparam <N> Numero delle componenti da includere nel calcolo. Inserendo un valore < 2 o > 4 
	/// sar&agrave; generato l'errore AECompileError::AE_VECTOR4F_NOT_IMPLEMENTED_FOR_THIS_VECTOR_LENGTH
	/// durante la compilazione.
	/// \remark Precisione di default impostata con AEMathAccuracyMode::AE_ACC_23_BIT.
	/// La sqrt negativa viene controllata con AEMathNegSqrtMode::AE_SQRT_SET_ZERO.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD>*</TD><TD></TD><TD></TD><TD></TD></TR></TABLE>
	template <AEINT32 N> AE_FORCEINLINE const AESimdFloat32 GetLength( void ) const;
	
	/// \brief Ritorna la lunghezza di questo vettore rappresentato dalle N componenti.
	/// \code return sqrt(this dot this) \endcode
	/// \tparam <N> Numero delle componenti da includere nel calcolo. Inserendo un valore < 2 o > 4 
	/// sar&agrave; generato l'errore AECompileError::AE_VECTOR4F_NOT_IMPLEMENTED_FOR_THIS_VECTOR_LENGTH
	/// durante la compilazione.
	/// \tparam <A> Imposta la precisione tramite \ref AEMathAccuracyMode.
	/// \tparam <S> Controlla le sqrt negative tramite \ref AEMathNegSqrtMode.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD>*</TD><TD></TD><TD></TD><TD></TD></TR></TABLE>
	template <AEINT32 N, AEMathAccuracyMode A, AEMathNegSqrtMode S> AE_FORCEINLINE const AESimdFloat32 GetLength( void ) const;

	/// \brief Ritorna la lunghezza di questo vettore rappresentato dalle N componenti, senza
	/// eseguire la sqrt.
	/// \code return (this dot this) \endcode
	/// \tparam <N> Numero delle componenti da includere nel calcolo. Inserendo un valore < 2 o > 4 
	/// sar&agrave; generato l'errore AECompileError::AE_VECTOR4F_NOT_IMPLEMENTED_FOR_THIS_VECTOR_LENGTH
	/// durante la compilazione.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD>*</TD><TD></TD><TD></TD><TD></TD></TR></TABLE>
	template <AEINT32 N> AE_FORCEINLINE const AESimdFloat32 GetLengthSquared( void ) const;
	
	/// \brief Ritorna la lunghezza inversa di questo vettore rappresentato dalle N componenti.
	/// \code return 1/sqrt(this dot this) \endcode
	/// \tparam <N> Numero delle componenti da includere nel calcolo. Inserendo un valore < 2 o > 4 
	/// sar&agrave; generato l'errore AECompileError::AE_VECTOR4F_NOT_IMPLEMENTED_FOR_THIS_VECTOR_LENGTH
	/// durante la compilazione.
	/// \remark Precisione di default impostata con AEMathAccuracyMode::AE_ACC_23_BIT.
	/// La sqrt negativa viene controllata con AEMathNegSqrtMode::AE_SQRT_SET_ZERO.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD>*</TD><TD></TD><TD></TD><TD></TD></TR></TABLE>
	template <AEINT32 N> AE_FORCEINLINE const AESimdFloat32 GetLengthInverse( void ) const;

	/// \brief Ritorna la lunghezza inversa di questo vettore rappresentato dalle N componenti.
	/// \code return 1/sqrt(this dot this) \endcode
	/// \tparam <N> Numero delle componenti da includere nel calcolo. Inserendo un valore < 2 o > 4 
	/// sar&agrave; generato l'errore AECompileError::AE_VECTOR4F_NOT_IMPLEMENTED_FOR_THIS_VECTOR_LENGTH
	/// durante la compilazione.
	/// \tparam <A> Imposta la precisione tramite \ref AEMathAccuracyMode.
	/// \tparam <S> Controlla le sqrt negative tramite \ref AEMathNegSqrtMode.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD>*</TD><TD></TD><TD></TD><TD></TD></TR></TABLE>
	template <AEINT32 N, AEMathAccuracyMode A, AEMathNegSqrtMode S> AE_FORCEINLINE const AESimdFloat32 GetLengthInverse( void ) const;
	
	/// \brief Normalizza se stesso come un vettore di N componenti.
	/// Le componenti non utilizzate nel calcolo potrebbero assumere un valore indefinito.
	/// \code  this = |this| \endcode
	/// \tparam <N> Numero delle componenti da includere nel calcolo. Inserendo un valore < 2 o > 4 
	/// sar&agrave; generato l'errore AECompileError::AE_VECTOR4F_NOT_IMPLEMENTED_FOR_THIS_VECTOR_LENGTH
	/// durante la compilazione.
	/// \remark Precisione di default impostata con AEMathAccuracyMode::AE_ACC_23_BIT.
	/// La sqrt negativa viene controllata con AEMathNegSqrtMode::AE_SQRT_SET_ZERO.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD>*</TD><TD></TD><TD></TD><TD></TD></TR></TABLE>
	template <AEINT32 N> AE_FORCEINLINE void Normalize( void );

	/// \brief Normalizza se stesso come un vettore di N componenti.
	/// Le componenti non utilizzate nel calcolo potrebbero assumere un valore indefinito.
	/// \code  this = |this| \endcode
	/// \tparam <N> Numero delle componenti da includere nel calcolo. Inserendo un valore < 2 o > 4 
	/// sar&agrave; generato l'errore AECompileError::AE_VECTOR4F_NOT_IMPLEMENTED_FOR_THIS_VECTOR_LENGTH
	/// durante la compilazione.
	/// \tparam <A> Imposta la precisione tramite \ref AEMathAccuracyMode.
	/// \tparam <S> Controlla le sqrt negative tramite \ref AEMathNegSqrtMode.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD>*</TD><TD></TD><TD></TD><TD></TD></TR></TABLE>
	template <AEINT32 N, AEMathAccuracyMode A, AEMathNegSqrtMode S> AE_FORCEINLINE void Normalize( void );
	
	/// \brief Normalizza se stesso come un vettore di N componenti e ritorna la lunghezza
	/// prima della normalizzazione.
	/// Le componenti non utilizzate nel calcolo potrebbero assumere un valore indefinito.
	/// \tparam <N> Numero delle componenti da includere nel calcolo. Inserendo un valore < 2 o > 4 
	/// sar&agrave; generato l'errore AECompileError::AE_VECTOR4F_NOT_IMPLEMENTED_FOR_THIS_VECTOR_LENGTH
	/// durante la compilazione.
	/// \remark Precisione di default impostata con AEMathAccuracyMode::AE_ACC_23_BIT.
	/// La sqrt negativa viene controllata con AEMathNegSqrtMode::AE_SQRT_SET_ZERO.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD>*</TD><TD></TD><TD></TD><TD></TD></TR></TABLE>
	template <AEINT32 N> AE_FORCEINLINE const AESimdFloat32 GetLengthAndNormalize( void );

	/// \brief Normalizza se stesso come un vettore di N componenti e ritorna la lunghezza
	/// prima della normalizzazione.
	/// Le componenti non utilizzate nel calcolo potrebbero assumere un valore indefinito.
	/// \tparam <N> Numero delle componenti da includere nel calcolo. Inserendo un valore < 2 o > 4 
	/// sar&agrave; generato l'errore AECompileError::AE_VECTOR4F_NOT_IMPLEMENTED_FOR_THIS_VECTOR_LENGTH
	/// durante la compilazione.
	/// \tparam <A> Imposta la precisione tramite \ref AEMathAccuracyMode.
	/// \tparam <S> Controlla le sqrt negative tramite \ref AEMathNegSqrtMode.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD>*</TD><TD></TD><TD></TD><TD></TD></TR></TABLE>
	template <AEINT32 N, AEMathAccuracyMode A, AEMathNegSqrtMode S> AE_FORCEINLINE const AESimdFloat32 GetLengthAndNormalize( void );

	/// \brief Ritorna la distanza Euclidea tra questo vettore e il punto indicato dal
	/// vettore passato come parametro.
	/// \code return len( this - vcVector ) \endcode
	/// \param vcVector Vettore contenente il punto con il quale misurare la distanza.
	/// \remark Precisione di default impostata con AEMathAccuracyMode::AE_ACC_23_BIT.
	/// La sqrt negativa viene controllata con AEMathNegSqrtMode::AE_SQRT_SET_ZERO.
	/// \return Un valore di tipo AESimdFloat32 che indica la distanza tra i due punti.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD>*</TD><TD></TD><TD></TD><TD></TD></TR></TABLE>
	AE_FORCEINLINE const AESimdFloat32 GetDistanceTo( AEVector4fRefParam vcVector ) const;

	/// \brief Ritorna la distanza Euclidea tra questo vettore e il punto indicato dal
	/// vettore passato come parametro.
	/// \code return len( this - vcVector ) \endcode
	/// \param vcVector Vettore contenente il punto con il quale misurare la distanza.
	/// \tparam <A> Imposta la precisione tramite \ref AEMathAccuracyMode.
	/// \tparam <S> Controlla le sqrt negative tramite \ref AEMathNegSqrtMode.
	/// \return Un valore di tipo AESimdFloat32 che indica la distanza tra i due punti.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD>*</TD><TD></TD><TD></TD><TD></TD></TR></TABLE>
	template <AEMathAccuracyMode A, AEMathNegSqrtMode S> AE_FORCEINLINE const AESimdFloat32 GetDistanceTo( AEVector4fRefParam vcVector ) const;

	/// \brief Ritorna la distanza Euclidea tra questo vettore e il punto indicato dal
	/// vettore passato come parametro, senza eseguire la sqrt.
	/// \code return len( this - vcVector ) \endcode
	/// \param vcVector Vettore contenente il punto con il quale misurare la distanza.
	/// \remark Precisione di default impostata con AEMathAccuracyMode::AE_ACC_23_BIT.
	/// La sqrt negativa viene controllata con AEMathNegSqrtMode::AE_SQRT_SET_ZERO.
	/// \return Un valore di tipo AESimdFloat32 che indica la distanza tra i due punti.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD>*</TD><TD></TD><TD></TD><TD></TD></TR></TABLE>
	AE_FORCEINLINE const AESimdFloat32 GetDistanceToSquared( AEVector4fRefParam vcVector ) const;

	/// Set the w component of self to the negative 3-component dot product of \a aPointOnPlane with self. The xyz components of self are unchanged.
	/// ( self.w = -p.dot<3>(self) )
	// INL
	AE_FORCEINLINE void SetPlaneConstant( AEVector4fRefParam vcPointOnPlane );

	/// @}
	/** @name Impostazione separata delle componenti XYZ e W */
	/// @{
	/// \brief Imposta le componenti X, Y e Z di questo vettore con il valore delle
	/// componenti XYZ del vettore \a vcXYZVector e la componente W con il valore W del
	/// vettore \a vcWVector.
	/// \param vcXYZVector Vettore dal quale prendere i valori X, Y e Z.
	/// \param vcWVector Vettore dal quale prendere il valore W.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD></TD><TD>*</TD><TD>*</TD><TD></TD></TR></TABLE>
	AE_FORCEINLINE void SetXYZ_W( AEVector4fRefParam vcXYZVector, AEVector4fRefParam vcWVector );

	/// \brief Imposta le componenti X, Y e Z di questo vettore con il valore delle
	/// componenti XYZ del vettore \a vcXYZVector e la componente W con il valore del
	/// parametro \a fW.
	/// \param vcXYZVector Vettore dal quale prendere i valori X, Y e Z.
	/// \param fW Valore da attribuire alla componente W.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD></TD><TD></TD><TD>*</TD><TD></TD></TR></TABLE>
	AE_FORCEINLINE void SetXYZ_W( AEVector4fRefParam vcXYZVector, AESimdFloat32ConstRef fW );

	/// \brief Imposta la componente W di questo vettore con il valore W del vettore \a vcWVector.
	/// \param vcWVector Vettore dal quale prendere il valore W.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD></TD><TD></TD><TD>*</TD><TD></TD></TR></TABLE>
	AE_FORCEINLINE void SetW( AEVector4fRefParam vcWVector );

	/// \brief Imposta la componente W di questo vettore con il valore del parametro \a fW.
	/// Gli altri componenti rimangono invariati.
	/// \param fW Valore da attribuire alla componente W.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD>*</TD><TD></TD><TD></TD><TD></TD></TR></TABLE>
	AE_FORCEINLINE void SetW( AESimdFloat32ConstRef fW );

	/// \brief Imposta le componenti X, Y e Z di questo vettore con il valore delle
	/// componenti XYZ del vettore \a vcXYZVector. La componente W rimane invariata.
	/// \param vcXYZVector Vettore dal quale prendere i valori X, Y e Z.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD></TD><TD></TD><TD>*</TD><TD></TD></TR></TABLE>
	AE_FORCEINLINE void SetXYZ( AEVector4fRefParam vcXYZVector );

	/// \brief Imposta le componenti X, Y e Z di questo vettore con il valore \a fValue.
	/// La componente W rimane invariata.
	/// \param fValue Valore da attribuire alle componenti X, Y e Z
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD></TD><TD></TD><TD>*</TD><TD></TD></TR></TABLE>
	AE_FORCEINLINE void SetXYZ( AEFLOAT32 fValue );

	/// \brief Imposta le componenti X, Y e Z di questo vettore con il valore \a fValue.
	/// La componente W rimane invariata.
	/// \param fValue Valore da attribuire alle componenti X, Y e Z
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD></TD><TD></TD><TD>*</TD><TD></TD></TR></TABLE>
	AE_FORCEINLINE void SetXYZ( AESimdFloat32ConstRef fValue );

	/// \brief Imposta le componenti X, Y e Z di questo vettore con il valore delle
	/// componenti XYZ del vettore \a vcXYZVector. La componente W sar&agrave; impostata a 0.
	/// \param vcXYZVector Vettore dal quale prendere i valori X, Y e Z.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD></TD><TD></TD><TD>*</TD><TD></TD></TR></TABLE>
	AE_FORCEINLINE void SetXYZ_0( AEVector4fRefParam vcXYZVector );

	/// Add the xyz components of \a v to the xyz components of self. The w component of self is undefined afterwards.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD></TD><TD></TD><TD>*</TD><TD></TD></TR></TABLE>
	AE_FORCEINLINE void AddXYZ( AEVector4fRefParam vcXYZVector );

	/// Subtract the xyz components of \a v from the xyz components of self. The w component of self is undefined afterwards.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD></TD><TD></TD><TD>*</TD><TD></TD></TR></TABLE>
	AE_FORCEINLINE void SubXYZ( AEVector4fRefParam vcXYZVector );

	/// Sets value of component I.  (0,1,2,3) correspond to the (x,y,z,w) components respectively.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD></TD><TD>*</TD><TD>*</TD><TD></TD></TR></TABLE>
	template <AEINT32 I> AE_FORCEINLINE void SetComponent( AESimdFloat32ConstRef fValue );

	/// Sets value of component \a i.  (0,1,2,3) correspond to the (x,y,z,w) components respectively.
	/// \remark Use this method only when the component index is not a compile time constant.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD></TD><TD>*</TD><TD>*</TD><TD></TD></TR></TABLE>
	AE_FORCEINLINE void SetComponent( const AEINT32 nIndex, AESimdFloat32ConstRef fValue );

	/// @}
	/** @name Controlli di comparazione */
	/// @{
	/// \brief Confronta che tutte le componenti di se stesso siano minori del
	/// vettore passato come parametro.
	/// \param vcVector Vettore da confrontare.
	/// \return Ritorna una maschera di bit con l'esito del confronto.
	AE_FORCEINLINE const AEVector4fComparison CmpL( AEVector4fRefParam vcVector ) const;

	/// \brief Confronta che tutte le componenti di se stesso siano minori o uguali del
	/// vettore passato come parametro.
	/// \param vcVector Vettore da confrontare.
	/// \return Ritorna una maschera di bit con l'esito del confronto.
	AE_FORCEINLINE const AEVector4fComparison CmpLE( AEVector4fRefParam vcVector ) const;

	/// \brief Confronta che tutte le componenti di se stesso siano maggiori del
	/// vettore passato come parametro.
	/// \param vcVector Vettore da confrontare.
	/// \return Ritorna una maschera di bit con l'esito del confronto.
	AE_FORCEINLINE const AEVector4fComparison CmpG( AEVector4fRefParam vcVector ) const;

	/// \brief Confronta che tutte le componenti di se stesso siano maggiori o uguali del
	/// vettore passato come parametro.
	/// \param vcVector Vettore da confrontare.
	/// \return Ritorna una maschera di bit con l'esito del confronto.
	AE_FORCEINLINE const AEVector4fComparison CmpGE( AEVector4fRefParam vcVector ) const;

	/// \brief Confronta che tutte le componenti di se stesso siano uguali al
	/// vettore passato come parametro.
	/// \param vcVector Vettore da confrontare.
	/// \return Ritorna una maschera di bit con l'esito del confronto.
	AE_FORCEINLINE const AEVector4fComparison CmpE( AEVector4fRefParam vcVector ) const;

	/// \brief Confronta che tutte le componenti di se stesso siano diverse dal
	/// vettore passato come parametro.
	/// \param vcVector Vettore da confrontare.
	/// \return Ritorna una maschera di bit con l'esito del confronto.
	AE_FORCEINLINE const AEVector4fComparison CmpNE( AEVector4fRefParam vcVector ) const;

	/// \brief Confronta che tutte le componenti di se stesso siano minori di 0.
	/// \return Ritorna una maschera di bit con l'esito del confronto.
	AE_FORCEINLINE const AEVector4fComparison LessZero( void ) const;

	/// \brief Confronta che tutte le componenti di se stesso siano minori o uguali a 0.
	/// \return Ritorna una maschera di bit con l'esito del confronto.
	AE_FORCEINLINE const AEVector4fComparison LessEqualZero( void ) const;

	/// \brief Confronta che tutte le componenti di se stesso siano maggiori di 0.
	/// \return Ritorna una maschera di bit con l'esito del confronto.
	AE_FORCEINLINE const AEVector4fComparison GreaterZero( void ) const;

	/// \brief Confronta che tutte le componenti di se stesso siano maggiori o uguali a 0.
	/// \return Ritorna una maschera di bit con l'esito del confronto.
	AE_FORCEINLINE const AEVector4fComparison GreaterEqualZero( void ) const;

	/// \brief Confronta che tutte le componenti di se stesso siano uguali a 0.
	/// \return Ritorna una maschera di bit con l'esito del confronto.
	AE_FORCEINLINE const AEVector4fComparison EqualZero( void ) const;

	/// \brief Confronta che tutte le componenti di se stesso siano diverse da 0.
	/// \return Ritorna una maschera di bit con l'esito del confronto.
	AE_FORCEINLINE const AEVector4fComparison NotEqualZero( void ) const;

	/// Component-wise select values from \a trueValue or \a falseValue depending on whether
	/// the component is marked true or false in the \a compareMask. ( self = mask ? trueValue : falseValue )
	AE_FORCEINLINE void SetSelect( AEVector4fConstRefCompParam vcCompareMask, AEVector4fRefParam vcTrueValue, AEVector4fRefParam vcFalseValue );

	/// Component-wise select values from \a trueValue or \a falseValue depending on whether
	/// the component is marked true or false in the template mask. ( self = mask ? trueValue : falseValue )
	template<AEVector4ComparisonMask::Mask M> AE_FORCEINLINE void SetSelect( AEVector4fRefParam vcTrueValue, AEVector4fRefParam vcFalseValue );

	/// Component-wise sign test whether negative sign is set, in which case the corresponding flag in the returned mask is set to true. ( self <= -0 ).
	/// This includes detecting floating point -0.0 which also returns true. Use the compare methods to perform arithmetic
	/// compares on the floating point value.
	// SSE
	AE_FORCEINLINE const AEVector4fComparison SignBitSet( void ) const;

	/// Component-wise sign test whether negative sign is clear, in which case the corresponding flag in the returned mask is set to true. ( self >= +0 ).
	/// This includes detecting floating point +0.0 which also returns true. Use the compare methods to perform arithmetic
	/// compares on the floating point value.
	// SSE
	AE_FORCEINLINE const AEVector4fComparison SignBitClear( void ) const;

	/// @}
	/** @name Controlli di validit&agrave; */
	/// @{
	/// Returns true if the first N components are valid finite floating point numbers.
	/// SSE FPU
	template <AEINT32 N> AE_FORCEINLINE AEBOOL32 IsOk( void ) const;

	/// \brief
	///   Checks whether this vector has a length of 1, within some epsilon range.
	///
	/// \param fEpsilon
	///   The maximum deviation that is allowed. The default value is reasonably large to handle the most common cases.
	///
	/// \sa AEMath::isFloatEqual
	template <AEINT32 N> AE_FORCEINLINE bool IsNormalized( AEFLOAT32 fEpsilon ) const;

	/// @}
	/** @name Operazioni di Load e Store */
	/// @{
	/// \brief Carica nel vettore N componenti da un puntatore AEDOUBLE64. Le componenti non caricate
	/// assumono un valore indefinito. Il puntatore lpAddr deve essere allineato per le
	/// operazioni SIMD.
	/// \param lpAddr Puntatore ad un indirizzo AEDOUBLE64.
	/// \tparam <N> Numero delle componenti da caricare.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD></TD><TD>*</TD><TD>*</TD><TD></TD></TR></TABLE>
	template <AEINT32 N> AE_FORCEINLINE void Load( const AEDOUBLE64 *lpAddr );

	/// \brief Carica nel vettore N componenti da un puntatore AEFLOAT32. Le componenti non caricate
	/// assumono un valore indefinito. Il puntatore lpAddr deve essere allineato per le
	/// operazioni SIMD.
	/// \param lpAddr Puntatore ad un indirizzo AEFLOAT32.
	/// \tparam <N> Numero delle componenti da caricare.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD></TD><TD>*</TD><TD>*</TD><TD></TD></TR></TABLE>
	template <AEINT32 N> AE_FORCEINLINE void Load( const AEFLOAT32 *lpAddr );

	/// \brief Carica nel vettore N componenti da un puntatore AEDOUBLE64. Le componenti non caricate
	/// assumono un valore indefinito. L'allineamento del puntatore lpAddr &egrave; impostato
	/// tramite il parametro template AEMathIoMode.
	/// \param lpAddr Puntatore ad un indirizzo AEDOUBLE64.
	/// \tparam <N> Numero delle componenti da caricare.
	/// \tparam <A> Parametri di allineamento \ref AEMathIoMode.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD></TD><TD>*</TD><TD>*</TD><TD></TD></TR></TABLE>
	template <AEINT32 N, AEMathIoMode A> AE_FORCEINLINE void Load( const AEDOUBLE64 *lpAddr );

	/// \brief Carica nel vettore N componenti da un puntatore AEFLOAT32. Le componenti non caricate
	/// assumono un valore indefinito. L'allineamento del puntatore lpAddr &egrave; gestito
	/// tramite il parametro template AEMathIoMode.
	/// \param lpAddr Puntatore ad un indirizzo AEFLOAT32.
	/// \tparam <N> Numero delle componenti da caricare.
	/// \tparam <A> Parametri di allineamento \ref AEMathIoMode.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD></TD><TD>*</TD><TD>*</TD><TD></TD></TR></TABLE>
	template <AEINT32 N, AEMathIoMode A> AE_FORCEINLINE void Load( const AEFLOAT32 *lpAddr );

	/// \brief Salva nell'indirizzo lpAddr N componenti del vettore, utilizzando
	/// l'arrotondamento di default del sistema.
	/// Il puntatore lpAddr deve essere allineato per le operazioni SIMD.
	/// \param lpAddr Puntatore ad un indirizzo AEDOUBLE64.
	/// \tparam <N> Numero delle componenti da caricare.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD></TD><TD>*</TD><TD>*</TD><TD></TD></TR></TABLE>
	template <AEINT32 N> AE_FORCEINLINE void Store( AEDOUBLE64 *lpAddr ) const;

	/// \brief Salva nell'indirizzo lpAddr N componenti del vettore, utilizzando
	/// l'arrotondamento di default del sistema.
	/// Il puntatore lpAddr deve essere allineato per le operazioni SIMD.
	/// \param lpAddr Puntatore ad un indirizzo AEFLOAT32.
	/// \tparam <N> Numero delle componenti da caricare.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD></TD><TD>*</TD><TD>*</TD><TD></TD></TR></TABLE>
	template <AEINT32 N> AE_FORCEINLINE void Store( AEFLOAT32 *lpAddr ) const;

	/// \brief Store double precision floating point values of N components to linear addresses at \a p.
	/// See the documentation at the template values for the requested IO mode.
	/// \param lpAddr Puntatore ad un indirizzo AEDOUBLE64.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD></TD><TD>*</TD><TD>*</TD><TD></TD></TR></TABLE>
	template <AEINT32 N, AEMathIoMode A, AEMathRoundingMode R> AE_FORCEINLINE void Store( AEDOUBLE64 *lpAddr ) const;

	/// \brief Store single precision floating point values of N components to linear addresses at \a p.
	/// See the documentation at the template values for the requested IO mode.
	/// \param lpAddr Puntatore ad un indirizzo AEFLOAT32.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD></TD><TD>*</TD><TD>*</TD><TD></TD></TR></TABLE>
	template <AEINT32 N, AEMathIoMode A, AEMathRoundingMode R> AE_FORCEINLINE void Store( AEFLOAT32 *lpAddr ) const;

	/// \brief Store double precision floating point values of N components to linear addresses at \a p.
	/// The rounding is the system default.
	/// See the documentation at the template values for the requested IO mode.
	/// \param lpAddr Puntatore ad un indirizzo AEDOUBLE64.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD></TD><TD>*</TD><TD>*</TD><TD></TD></TR></TABLE>
	template <AEINT32 N, AEMathIoMode A> AE_FORCEINLINE void Store( AEDOUBLE64 *lpAddr ) const;

	/// \brief Store single precision floating point values of N components to linear addresses at \a p.
	/// The rounding is the system default.
	/// See the documentation at the template values for the requested IO mode.
	/// \param lpAddr Puntatore ad un indirizzo AEFLOAT32.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD></TD><TD>*</TD><TD>*</TD><TD></TD></TR></TABLE>
	template <AEINT32 N, AEMathIoMode A> AE_FORCEINLINE void Store( AEFLOAT32 *lpAddr ) const;
		
	/// @}
	/** @name Operatori */
	/// @{

	/// Sets all components from \a v. This operator is register aliasing safe. ( self = v )
	// INL
	AE_FORCEINLINE void operator= ( AEVector4fRefParam vcVector );

	/// Gives read/write access to element i.  (0,1,2,3) correspond to the (x,y,z,w) components respectively.
	/// \remark Use this method only for storage purposes or immediate manipulation when the component index is not a compile time constant.
	// SSE FPU
	AE_FORCEINLINE AEFLOAT32 &operator() ( AEINT32 nIndex );

	/// Gives read only access to element i.  (0,1,2,3) correspond to the (x,y,z,w) components respectively.
	/// \remark Use this method only for storage purposes when the component index is not a compile time constant.
	// SSE FPU
	AE_FORCEINLINE const AEFLOAT32 &operator() ( AEINT32 nIndex ) const;

	/// @}
	/** @name Accesso componenti */
	/// @{
	/// \brief Ritorna la componente I-esima del vettore.
	/// \tparam I Indice della componente (0,1,2,3) corrispondono rispettivamente 
	/// alle componenti (X, Y, Z, W).
	/// \return Un AESimdFloat32 conenente il valore della componente selezionata.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD></TD><TD>*</TD><TD>*</TD><TD></TD></TR></TABLE>
	template <AEINT32 I> AE_FORCEINLINE const AESimdFloat32 GetComponent( void ) const;

	/// \brief Ritorna la componente I-esima del vettore.
	/// \param nIndex Indice della componente (0, 1, 2, 3) corrispondono rispettivamente 
	/// alle componenti (X, Y, Z, W).
	/// \remark Utilizzare questo metodo solo se l'indice della componente non &egrave;
	/// conosciuto durante la compilazione.
	/// \return Un AESimdFloat32 conenente il valore della componente selezionata.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD></TD><TD>*</TD><TD>*</TD><TD></TD></TR></TABLE>
	AE_FORCEINLINE const AESimdFloat32 GetComponent( const AEINT32 nIndex ) const;

	/// \brief Ritorna la componente X del vettore.
	/// \return Un AESimdFloat32 conenente il valore della componente X di questo vettore.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD>*</TD><TD></TD><TD></TD><TD></TD></TR></TABLE>
	AE_FORCEINLINE const AESimdFloat32 GetX( void ) const;

	/// \brief Ritorna la componente Y del vettore.
	/// \return Un AESimdFloat32 conenente il valore della componente Y di questo vettore.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD>*</TD><TD></TD><TD></TD><TD></TD></TR></TABLE>
	AE_FORCEINLINE const AESimdFloat32 GetY( void ) const;
	
	/// \brief Ritorna la componente Z del vettore.
	/// \return Un AESimdFloat32 conenente il valore della componente Z di questo vettore.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD>*</TD><TD></TD><TD></TD><TD></TD></TR></TABLE>
	AE_FORCEINLINE const AESimdFloat32 GetZ( void ) const;

	/// \brief Ritorna la componente W del vettore.
	/// \return Un AESimdFloat32 conenente il valore della componente W di questo vettore.
	/// \version
	/// <TABLE><TR><TD>INL</TD><TD>FPU</TD><TD>SSE</TD><TD>NEON</TD></TR>
	/// <TR><TD>*</TD><TD></TD><TD></TD><TD></TD></TR></TABLE>
	AE_FORCEINLINE const AESimdFloat32 GetW( void ) const;

	/// @}
	/** @name Lunghezza e distanza */
	/// @{

	// SSE
	AE_FORCEINLINE void SetFlipSign( AEVector4fRefParam vcVector, AEVector4fRefParam vSign );

	/// Component-wise copy values from \a v while flipping the sign of each value if the scalar value of \a sSign is negative. ( self = (sSign < 0) ? -v : v )
	// SSE
	AE_FORCEINLINE void SetFlipSign( AEVector4fRefParam vcVector, AEVector4fConstRefCompParam sSign );


	/// \brief
	///   Normalizes the vector, if its length is non-zero. Otherwise the vector will stay unmodified.
	///
	/// If normalization was not possible, it returns HKV_FAILURE otherwise HKV_SUCCESS.
	/// In case of failure the vector will not be modified. That means the vector will either be all zero
	///( and thus zero-length) or some component is invalid( +/-Infinity or NaN).
	///
	/// \param fEpsilon If all values are in range [-fEpsilon; +fEpsilon] the vector is considered to be 'zero'.
	///
	/// \sa AEVector4f::Normalize
	/// \sa AEVector4f::NormalizedEnsureUnitLength
	template <AEINT32 N> AE_FORCEINLINE AEBOOL32 NormalizeIfNotZero( void );

	template <AEINT32 N, AEMathAccuracyMode A, AEMathNegSqrtMode S>AE_FORCEINLINE AEBOOL32 NormalizeIfNotZero( void );
	/// \brief
	///   Normalizes this vector under all circumstances and returns its previous length.
	///
	/// If the vector can not be normalized, its x component will be set to 1 and all other components to 0.
	/// In this case the function will return 0, as the vectors previous length was 0( or invalid).
	/// If the vector can be normalized, the previous length is returned.
	///
	/// \sa AEVector4f::Normalize
	/// \sa AEVector4f::NormalizeIfNotZero
	AE_FORCEINLINE float NormalizedEnsureUnitLength( void );

	/// @}
	/** @name Modifica delle componenti */
	/// @{

	/// \brief
	///   Each component of this vector is set to the minimum of lhs and the corresponding component of rhs.
	/// SSE
	AE_FORCEINLINE void SetMin( AEVector4fRefParam vcVector1, AEVector4fRefParam vcVector2 );

	/// \brief
	///   Each component of this vector is set to the maximum of lhs and the corresponding component of rhs.
	AE_FORCEINLINE void SetMax( AEVector4fRefParam vcVector1, AEVector4fRefParam vcVector2 );

	/// \brief
	///   Each component of this vector is set to val clamped to the min/max range defined by vcMinVal and vcMaxVal.
	AE_FORCEINLINE void SetClamped( const AEVector4fRefParam vcVal, const AEVector4fRefParam vcMinVal, const AEVector4fRefParam vcMaxVal );

	/// \brief
	///   All components of this vector are set to the absolute value of the corresponding component of val.
	/// SSE
	AE_FORCEINLINE void SetAbs( AEVector4fRefParam vcVector );

	AE_FORCEINLINE void SetRotatedDir( const AEMatrix3f &mtMatrix, AEVector4fRefParam vcVector );

	/// Sets self to the vector \a b rotated by the inverse matrix of \a a.
	/// This method is enforced inline.
	AE_FORCEINLINE void SetRotatedInverseDir( const AEMatrix3f &mtMatrix, AEVector4fRefParam vcVector );

	/// @}
	/** @name Funzioni di utilit&agrave; */
	/// @{

	/// \brief
	///   Sets this vector to the linear interpolation of lhs and rhs using t as the interpolation factor.
	AE_FORCEINLINE void SetInterpolate( AEVector4fRefParam vcVector1, AEVector4fRefParam vcVector2, AESimdFloat32ConstRef fValue );

	/// @}


};

AE_FORCEINLINE AEBOOL32 operator== ( const AEVector4f &vcLhs, const AEVector4f &vcRhs );
#endif // _AEVECTOR4F_H_

